package org.batatasframework.strategy;

import java.io.IOException;

import javax.servlet.ServletException;

import org.batatasframework.common.ParameterReader;
import org.batatasframework.manager.HtmlDetailBuilder;
import org.batatasframework.manager.RuntimeStrategyManaged;
import org.springframework.security.core.session.SessionRegistry;

/**
 * 限制一个服务器登录的人数；这里需要改用智能的处理策略：
 * 
 * 根据当前半小时内或几分钟内的服务器平均处理时间的情况来决定是否实施限流措施
 * 
 * 这里必须得开放某些账户不进行限制
 * 
 * @author jackson
 *
 */
public class ServerStrategyLimitable extends AbstractServiceStrategyHandler implements RuntimeStrategyManaged{
	
	/** 原来定义文件里定义的限制，允许在服务器运行时动态修改这个限制的值 */
	private int limitSource;
	
	/** 比如说某个服务器只限制1000个登录用户访问 */
	private int limit;
	
	private SessionRegistry sessionRegistry;
	
	public ServerStrategyLimitable() {
		super("LIMITABLE", "高峰限流");
	}
	
	@Override
	protected ServerStrategyResult internalExecute(ServerStrategyEvent event) throws IOException, ServletException {
		
		/*
		 * 这里可能需要启动智能的计算，不然如果有几千个人登录，但没进行什么操作，
		 * 就会导致后来的人登录不上去的。所以这里除了直接使用人数进行限制外，还需要
		 * 根据处理的时间等进行智能的判断，决定是否需要采用限制措施。
		 */
		
		//不启动限制措施
		//对于已经登录的用户，则不实行限流措施
		if(limit <= 0 || event.hasLogon()) return ServerStrategyResult.CONTINUE;
		
		int currentCount = sessionRegistry.getAllPrincipals().size();
		//未达到人数的限流要求，这个属于直接限流，是否使用这种方式？或是否优先使用这种方式
		if(limit > currentCount) return ServerStrategyResult.CONTINUE;
		
		/*
		 * 这里是考虑使用限制措施的，但要使用何种限流的方式？
		 * 通过智能判断的方式使用动态限制的措施，即达到什么值就不允许登录了
		 * 这里生成提示界面，并不允许登录
		 * 
		 * TODO 智能判断并使用限制措施
		 */

		return ServerStrategyResult.RETURN;
	}

	protected String generateDeniedAccessHtml(ServerStrategyEvent event) {
		StringBuilder sb = new StringBuilder();
		sb.append("<html><head><title>服务器繁忙</title>");
		sb.append("<link rel='stylesheet' type='text/css' href='/res/css/layout/blue/layout.css'>");
		sb.append("</head><body style='margin:0'>");
		sb.append("<div id='Busy'><div id='BusyBG'></div><div id='BusyBGColor'></div><div id='BusyFont'></div></div>");
		sb.append("</body></html>");
		return sb.toString();
	}
	  
	public void reset(){
		limit = limitSource;
	}
	
	public void setLimit(int limit) {
		this.limit = limit;
		this.limitSource = limit;
	}
	
	public void setSessionRegistry(SessionRegistry sessionRegistry) {
		this.sessionRegistry = sessionRegistry;
	}
	
	private final HtmlDetailBuilder htmlBuilder = new HtmlDetailBuilder(){

		@Override
		public String getId() {
			return id;
		}

		@Override
		public String getName() {
			return name;
		}

		@Override
		public String getHtml() {
			StringBuilder html = new StringBuilder();
			
			html.append("限值：");
			html.append("<input type='text' name='limit' value='").append(limit).append("'  ");
			html.append("style='width:50px;' title='默认值：").append(limitSource).append("'/>");
			int currentCount = sessionRegistry.getAllPrincipals().size();
			html.append("；当前登录人数：").append(currentCount).append('/');
			if(limit > 0){
				html.append(limit);
			}else{
				html.append("无限制");
			}
			
			return html.toString();
		}

		@Override
		public boolean isEditable() {
			return true;
		}
	};
	
	@Override
	public HtmlDetailBuilder getHtmlBuilder() {
		return htmlBuilder;
	}
	
	@Override
	public void save(ParameterReader paraReader) throws Exception {
		limit = paraReader.getInteger("limit", 0);
	}
}
